<template>
  <div class="monaco" id="monaco" ref="monacoRef"></div>
</template>

<script setup>
import * as monaco from "monaco-editor";
import { onMounted, ref, onBeforeUnmount, watch } from "vue";

// 设置Props默认值
const props = defineProps({
  code: String,
  theme: {
    type: String,
    default: "vs"
  },
  language: {
    type: String,
    default: "javascript"
  },
  getEditor: {
    type: Function,
    default: () => { }
  }
});

// DOM引用和响应式变量
const monacoRef = ref(null); // Monaco编辑器容器引用
let editor = null; // 编辑器实例

/**
 * 初始化Monaco编辑器
 */
const initEditor = () => {
  if (!monacoRef.value) return;

  // 创建编辑器实例
  editor = monaco.editor.create(monacoRef.value, {
    value: props.code, // 初始代码
    language: props.language, // 语言模式
    theme: props.theme, // 主题样式
    automaticLayout: true, // 自动调整布局
    lineHeight: 24, // 行高
    tabSize: 2, // Tab缩进大小
    fontSize: 16, // 字体大小
  });

  // 将编辑器实例传递给父组件
  props.getEditor(editor);
};

const decorationsCollection =
  ref(null);

const highlightLine = (lineNumber = 0) => {
  if (!editor) return;

  // 初始化装饰器集合（如果尚未创建）
  if (!decorationsCollection.value) {
    decorationsCollection.value = editor.createDecorationsCollection([]);
  }

  // 如果行号为0则清除所有高亮
  if (lineNumber === 0) {
    decorationsCollection.value.clear();
    return;
  }

  // 设置新的行高亮装饰器
  decorationsCollection.value.set([
    {
      range: new monaco.Range(lineNumber, 1, lineNumber, 1),
      options: {
        isWholeLine: true,
        className: "highlight-line",
        stickiness:
          monaco.editor.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
      },
    },
  ]);
};

/**
 * 设置编辑器语言模式
 */
const setLanguage = () => {
  if (!editor) return;

  const model = editor.getModel();
  if (!model) return;

  // 更新模型的语言模式
  monaco.editor.setModelLanguage(model, props.language);
};

/**
 * 滚动到指定行并居中显示
 * @param lineNumber 要滚动到的行号（默认第0行）
 */
const scrollToLine = (lineNumber = 0) => {
  if (!editor) return;
  editor.revealLineInCenter(lineNumber);
};

/**
 * 更新编辑器内容
 */
const updateEditorContent = () => {
  if (!editor) return;

  // 设置新的代码内容
  editor.setValue(props.code);

  // 如果有代码内容，则更新语言模式、滚动位置和高亮
  if (props.code) {
    setLanguage();
    scrollToLine(0);
    highlightLine(0);
  }
};

/**
 * 切换编辑器主题
 */
const changeTheme = () => {
  if (!editor) return;
  monaco.editor.setTheme(props.theme);
};

// 监听代码内容变化
watch(() => props.code, updateEditorContent, { immediate: true });

// 监听主题变化
watch(() => props.theme, changeTheme, { immediate: true });

// 组件挂载时初始化编辑器
onMounted(() => {
  initEditor();
});

// 组件卸载前清理编辑器
onBeforeUnmount(() => {
  if (editor) {
    editor.dispose(); // 释放编辑器资源
    editor = null; // 清空引用
  }
});
</script>

<style scoped lang="scss">
.monaco {
  width: 100%;
  height: 100%;
}
</style>

<style>
/* 高亮行的样式 */
#monaco .highlight-line {
  background-color: rgba(140, 143, 255, 0.7) !important;
}
</style>
